Containers (STL)
The container types are divided into the three major categories **sequence containers**, **associative containers**, and **container adapters**. The first two are collectively referred to as first-class containers. The sequence containers represent linear data structures, such as vectors and linked lists. Vector is the only container relevant for EKSAMEN. When preparing to use a Standard Library container, it's important to ensure that the type of element being stored in the container supports a minimum set of functionality. When an element is inserted into a container, a copy of that element is made. For this reason, the element type should provide its own copy constructor and assignment operator. Note that this is required only if default memberwise copy and default memberwise assignment do not perform proper copy and assignment operations for the element type. Also, the associative containers and many algorithms require elements to be compared. For this reason, the element type should provide an equality operator and a less-than operator <. Container Common Functions Most containers provide similar functionality. Many generic operations, such as member function size, apply to all containers, and other operations apply to subsets of similar containers. This enourages extensibility of the Standard Library with new classes. A list of common functions to all Standard Library containers: ^ Function ^ Description ^ | default constructor | A constructor that initializes an empty container. Normally, each container has several constructors that provide different initialization methods for the container. | | copy constructor | A constructor that initializes the containre to be a copy of an existing container of the same type. | | destructor | Destructor function for cleanup after a container is no longer needed. | | empty | Returns true if there are no elements in the container; otherwise, returns false. | | insert | Inserts an item in the container. | | size | Returns the number of elements currently in the container. | | operator= | Assigns one container to another. | | operator< | Returns true if the contents of the first container is less than the second; otherwise, returns false. | | operator<= | Returns true if the contents of the first container is less than or equal to the second; otherwise, returns false. | | operator> | Returns true if the contents of the first container is greater than the second; otherwise, returns false. | | operator>= | Returns true if the contents of the first container is greater than or equal to the second; otherwise, returns false. | | operator | Returns true if the contents of the first container is equal to the second; otherwise, returns false. | | operator!= | Returns true if the contents of the first container is not equal to the second; otherwise, returns false. | | swap | Swaps the elements of two containers. | Functions found only in the first-class containers: ^ Function ^ Description ^ | max_size | Returns the maximum number of elements for a container. | | begin | The two versions of this function return either an iterator or a const_iterator that refers to the first element of the container. | | end | The two versions of this function return either an iterator or a const_iterator that refers to the next position after the end of the container. | | rbegin | The two versions of this function return either a reverse_iterator or a const_reverse_iterator that refers to the last element of the container. | | rend | The two versions of this function return either a reverse_iterator or a const_reverse_iterator that refers to next position after the last element of the container. | | erase | Erases one or more elements from the container. | | clear | Erases all elements from the container. | Sequence Containers The Standard Library provides the three sequence containers **vector**, **list**, and **deque**. Class template vector and class template deque both are based on arrays. Class template list implements a linked-list data structure. A vector changes its size dynamically, and they can be assigned to one another. This is not possible with pointer-based, C-like arrays, because those array names are constant pointers and thus cannot be the targets of assignments. Vector substripting does not perform automatic range checking, but class template vector does provide this capability via member function at. Insertion at the back of a vector is efficient. The vector simply grows, if necessary, to accomodate the new item. It's expensive to insert (or delete) an element in the middle of a vector - the entire portion of the vector after the insertion (or deletion) point must be moved, because vector elements occupy contiguous cells in memory. Beyond Container Common Functions, each container typically provides a variety of other capabilities. Many of these capabilities are common to several containers, but they're not always equally efficient for each container. You must choose the container most appropriate for the application. front return a reference to the first element in a non-empty container, back to return a reference to the last element in a non-empty container, push_back inserts a new element at the end of the container and pop_back removes the last element of the container. Applications that require frequent insertions and deletions at both ends of a container normally use a deque rather than a vector. Although we can insert and delete elements at the front and back of both a vector and a deque, class deque is more efficient than vector for doing insertions and deletions at the front. Applications with frequent insertions and deletions in the middle and/or at the extremes of a container normally use a list, due to its efficient implementation of insertion and deletion anywhere in the data structure. Vector Sequence Container Class template vector provides a data structure with contiguous memory locations. This enables efficient, direct access to any element of a vector via the subscript operator []. A vector is most commonly used when the data in the container must be easily accessible via a subscript or will be sorted. When a vector's memory is exchausted, teh vector allocates a larger contiguous area of memory, copies the original elements into the new memory and deallocates the old memory. Choose the vector container for best random-access performance. Objects of class template vector provide rapid indexed access with the overloaded subscript operator [] because they're stored in contiguous memory like a C or C++ raw array. It's faster to insert many elements into a container at once than one at a time. An important part of every container is the type of iterator it supports. This determines which algorithms can be applied to the container. A vector supports random-access iterators which means that all the Standard Library algorithms can operate on a vector. The following code illustrates several functions of the vector class template. Many of these functions are available in every first-class container: #include #include using namespace std; // prototype for function template printVector template void printVector(const vector& integers2); int main() { const int SIZE = 6; int arraySIZE = {1, 2, 3, 4, 5, 6}; vector integers; // create vector of ints cout << "The initial size of integers is: " << integers.size() << "\nThe initial capacity of integers is: " << integers.capacity(); // function push_back is in every sequence container integers.push_back(2); integers.push_back(3); integers.push_back(4); cout << "\nThe size of integers is: " << integers.size() << "\nThe capacity of integers is: " << integers.capacity(); cout << "\n\nOutput array using pointer notation: "; // display array using pointer notation for (int *ptr = array; ptr != array + SIZE; ++ptr) cout << *ptr << ' '; cout << "\nOutput vector using iterator notation: "; printVector(integers); cout << "\nReversed contents of vector integers: "; // two const reverse iterators vector::const_reverse_iterator reverseIterator; vector::const_reverse_iterator tempIterator = integers.rend(); // display vector in reverse order using reverse_iterator for (reverseIterator = integers.rbegin(); reverseIterator != tempIterator; ++reverseIterator) cout << *reverseIterator << ' '; cout << endl; } // function template for outputting vector elements template void printVector(const vector& integers2) { typename vector::const_iterator constIterator; // display vector element using const_iterator for (constIterator = integers2.begin(); constIterator != integers2.end(); ++constIterator) cout << *constIterator << ' '; } Output: The initial size of integers is: 0 The initial capacity of integers is: 0 The size of integers is: 3 The capacity of integers is: 4 Output array using pointer notation: 1 2 3 4 5 6 Output vector using iterator notation: 2 3 4 Reversed contents of vector integers: 4 3 2 It can be wasteful to double a vector's size when more space is needed. For example, a full vector of 1,000,000 elements resizes to accomodate 2,000,000 elements when a new element is added. This leaves 999,999 unused elements. You can use resize and reserve to control space usage better. Use prefix increment when applied to Standard Library iterators because the prefix increment operator does not have the overhead of returning a value that must be stored in a temporary object. Only random-access iterators support <. It's better to use != and end to test for the end of a container. Attempting to dereference an iterator positioned outside its container is a runtime logic error. In particular, the iterator returned by end cannot be dereferenced or incremented. For performance reasons, capture the loop ending value before the loop and compare against that, rather than having a (potentially expensive) function call for each iteration. References Category:Standard Library